/*           Copyright(c) 2005-2008 Dave Sexton            *
 *                   HtmlEditor Control                    *
 * http://www.codeplex.com/DocProject/Project/License.aspx *
 ***********************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Xml;
using DaveSexton.Controls.Resources;

namespace DaveSexton.Controls
{
	partial class HtmlToXmlConverter
	{
		private sealed class AttributeReader : HtmlParserBase
		{
			#region Public Properties
			public string Name
			{
				get
				{
					return name;
				}
			}

			public string Value
			{
				get
				{
					return value;
				}
			}
			#endregion

			#region Private / Protected
			private string name, value;
			#endregion

			#region Constructors
			/// <summary>
			/// Constructs a new instance of the <see cref="AttributeReader" /> class.
			/// </summary>
			public AttributeReader(TextReader reader, XmlWriter writer, List<string> booleanAttributeNames)
				: base(reader, writer, null, null, booleanAttributeNames)
			{
			}
			#endregion

			#region Methods
      [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")]
			public void Read(XmlNameProcessor attributeNameProcessor)
			{
				// The = character normally ends an attribute's name, but if the attirbute is a boolean attribute
				// then either white-space or the end of the parent tag (>) can end the attribute's name instead.
				name = ReadName(true, '=', '>');

				if (attributeNameProcessor != null)
					// NOTE: If name is null that will indicate to the AttributeReader class that the attribute should be skipped (read, but not written).
					name = attributeNameProcessor(name);

				SkipToContent(true, false);

				char c = PeekNextCharacter();

				if (c != '=')
				{
					if (name == null || booleanAttributes.Contains(name))
					{
						value = name;
						return;
					}

					throw new ArgumentException(string.Format(System.Globalization.CultureInfo.CurrentCulture,
						Errors.HtmlToXmlConverterMissingAttributeValue, name), "html");
				}

				reader.Read();		// skip '=' character

				SkipToContent(true, false);

				value = ReadValue();
			}

			private string ReadValue()
			{
				char? quote = null, c = PeekNextCharacter();

				if (c == AttributeQuote || c == AttributeQuoteAlternate)
				{
					quote = c;

					reader.Read();		// skip quote
				}

				StringBuilder attribute = new StringBuilder(32);

				PeekNextCharacter(false, delegate(char next)
				{
					if ((quote.HasValue) ? next == quote.Value : char.IsWhiteSpace(next) || next == TagEnd)
					// end of value
					{
						if (quote.HasValue)
							reader.Read();		// skip quote

						// break
						return false;
					}

					attribute.Append(ReadNext());

					// read next character
					return true;
				});

				return attribute.ToString();
			}
			#endregion
		}
	}
}
